/**
 * 
 */
package com.momosw.games.engine.simulator;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.momosw.games.engine.Game;
import com.momosw.games.engine.GameConfiguration;
import com.momosw.games.engine.GameNotOverException;
import com.momosw.games.engine.GameResults;
import com.momosw.games.engine.player.BuilderPlayer;
import com.momosw.games.engine.player.DummyPlayer;
import com.momosw.games.engine.player.Player;

/**
 * <b>Project:</b> JerichoCardGame<br />
 * <b>Package:</b> com.momosw.games.engine.simulator<br />
 * <b>Class:</b> Simulator.java<br />
 * <br />
 * <i>GSI 2011</i><br />
 *
 * @author Miguel Coronado (miguelcb84@gmail.com)
 * @version	Aug 23, 2011
 *
 */
public class Simulator {

    /**
     * This gathers the results archived by each player. The value consist on 
     * an array of integer values where the first integer indicated how many
     * times the player has won a game, the second value how many time he ended
     * in second position, and so on.
     */
    private Map<Player, int[]> rankin;
    /** */
    private List<GameResults> details;
    /** Just for pretty Print affairs */ 
    private Normalizer normalizer;
    
    /**
     * Constructor
     */
    public Simulator(List<Player> players) {
        details = new LinkedList<GameResults>();
        rankin = new HashMap<Player, int[]>();
        for(Player player : players){
            rankin.put(player, new int[players.size()]);
        }
        
        normalizer = new Normalizer(players);
    }
    
    /**
     * 
     * @param argsindex
     */
    public static void main (String[]args) {
        
        // simulations
        int simulations = 500;
        
        // Prepare the player list
        List<Player> players = new LinkedList<Player>();
        Player focus = new BuilderPlayer("Builder1");
        players.add(focus);
        players.add(new DummyPlayer("Dummy1"));
        players.add(new DummyPlayer("Dummy2"));
        players.add(new DummyPlayer("Dummy3"));
        
        // Create the simulator
        Simulator sim = new Simulator(players);
        
        // Execute the simulation
        for (int index = 0; index < simulations; index++) {
            Game game = new Game(new GameConfiguration(), players);
            game.start();
            do{ } while (!game.isOver());
            
            try {
                GameResults results = game.getResults();
                sim.archieve(results);
            } catch (GameNotOverException e) { /*continue*/ }
        
        }
        
        // Print results
        sim.printResults(focus);
    }
    
    /**
     * 
     * @param results
     */
    protected void archieve(GameResults results) {
        details.add(results);
        for (Player player : results.getPlayers()) {
            int rank = results.getRank(player);
            rankin.get(player)[rank-1]++;
        }
    }

    /**
     * 
     * @param player
     * @param position
     * @return
     */
    public int get(Player player, int position){
        return rankin.get(player)[position-1];
    }
    
    protected void printResults (Player focusOnPlayer) {
        System.out.println("Results for the execution of " + details.size() + " games.");
        System.out.println("Players:");
        for(Player player : rankin.keySet()){
            System.out.println("\t" + normalizer.normalize(player) + " (" + player.getClass().getSimpleName() + ")");
        }
        System.out.println("Rankin:");
        for(Player player : rankin.keySet()){
            int[] r = rankin.get(player);
            String str = "\t" + normalizer.normalize(player) + " ";
            for(int i = 0; i < r.length; i++){
                str += (i+1) + "º (" + r[i] + ") ";
            }
            System.out.println(str);
        }
        System.out.println();
        System.out.println("Details:");
        for(GameResults gr : details){
            System.out.println("\t" + gr.printSummary(focusOnPlayer));
        }
    }
}
